package profession_service

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/tealeg/xlsx"
	"io"
	"net/http"
	"peilian-api/app/global/databases/tables"
	"peilian-api/app/global/errors"
	"peilian-api/app/global/variable"
	"peilian-api/app/model"
	"peilian-api/utils/tools"
	"strings"
)

func GetProfession(ctx *gin.Context, req model.GetProfessionReq) (*model.GetProfessionResp, *errors.ErrRes) {
	resp := &model.GetProfessionResp{}
	var db = variable.DB.MySQL.Model(&tables.Profession{})
	if req.BelongToID != nil {
		db = db.Where("belong_to_id=?", *req.BelongToID)
	} else if req.Tier != "" {
		db = db.Where("tier=?", req.Tier)
	} else {
		db = db.Where("belong_to_id is NULL")
	}
	if req.Name != "" {
		db = db.Where("name like ?", "%"+req.Name+"%")
	}
	var allProfession []tables.Profession
	if err := db.Order("id desc").Find(&allProfession).Error; err != nil {
		return nil, errors.NewErrInfo(http.StatusInternalServerError, err)
	}
	for _, v := range allProfession {
		one := model.Profession{
			Id:         v.ID,
			Name:       v.Name,
			Tier:       v.Tier,
			BelongToID: v.BelongToID,
		}
		resp.Professions = append(resp.Professions, one)
	}
	resp.Total = len(allProfession)

	return resp, nil
}

func CreateProfession(ctx *gin.Context, req model.CreateProfessionReq) *errors.ErrRes {
	profession := tables.Profession{
		Tier:       req.Tier,
		Name:       req.Name,
		BelongToID: nil,
	}
	// 查询同等级的名字是否存在
	var db = variable.DB.MySQL.Model(&tables.Profession{}).Where("name = ?", req.Name)
	if req.BelongToID != nil {
		db = db.Where("belong_to_id=?", *req.BelongToID)
	} else {
		db = db.Where("belong_to_id is NULL")
	}
	var count int64
	if err := db.Count(&count).Error; err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, err)
	}
	if count > 0 {
		return errors.NewErrInfo(10001, fmt.Errorf("%s 该名字已存在", req.Name))
	}

	if req.BelongToID != nil {
		p, err := tables.GetProfessionById(*req.BelongToID)
		if err != nil {
			return errors.NewErrInfo(10004, fmt.Errorf("inner error :%+v", err))
		}
		if p.ID == 0 {
			return errors.NewErrInfo(10005, fmt.Errorf("父专业信息不存在"))
		}
		profession.BelongToID = req.BelongToID
	}

	if err := variable.DB.MySQL.Create(&profession).Error; err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, err)
	}

	return nil
}

func UpdateProfession(ctx *gin.Context, req model.UpdateProfessionReq) *errors.ErrRes {
	p, err := tables.GetProfessionById(req.Id)
	if err != nil {
		return errors.NewErrInfo(10004, fmt.Errorf("inner error :%+v", err))
	}
	if p.ID == 0 {
		return errors.NewErrInfo(10005, fmt.Errorf("专业信息不存在"))
	}
	// 查询同等级的名字是否存在
	var db = variable.DB.MySQL.Model(&tables.Profession{}).Where("name = ? and id != ?", req.Name, req.Id)
	if p.BelongToID != nil {
		db = db.Where("belong_to_id=?", *p.BelongToID)
	} else {
		db = db.Where("belong_to_id is NULL")
	}
	var count int64
	if err := db.Count(&count).Error; err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, err)
	}
	if count > 0 {
		return errors.NewErrInfo(10001, fmt.Errorf("%s 该名字已存在", req.Name))
	}

	result := variable.DB.MySQL.Model(&tables.Profession{}).Where("id=?", req.Id).Update("name", req.Name)
	if result.Error != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, result.Error)
	}
	return nil
}

func DeleteProfession(ctx *gin.Context, req model.DeleteProfessionReq) *errors.ErrRes {
	p, err := tables.GetProfessionById(req.Id)
	if err != nil {
		return errors.NewErrInfo(10004, fmt.Errorf("inner error :%+v", err))
	}
	if p.ID == 0 {
		return errors.NewErrInfo(10005, fmt.Errorf("专业信息不存在"))
	}
	result := variable.DB.MySQL.Model(&tables.Profession{}).Delete("id=?", req.Id)
	if result.Error != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, result.Error)
	}
	return nil
}

func ImportProfession(ctx *gin.Context) *errors.ErrRes {
	// 获取所有现在存在的信息
	var professions []tables.Profession
	if err := variable.DB.MySQL.Model(&tables.Profession{}).Order("id").Find(&professions).Error; err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, err)
	}
	var idToProMap = make(map[uint]tables.Profession)
	var nameToProMap = make(map[string]tables.Profession)
	for _, p := range professions {
		idToProMap[p.ID] = p
		// 组装姓名
		BelongToID := p.BelongToID
		var name = p.Name
		for BelongToID != nil {
			parentPro, exist := idToProMap[*BelongToID]
			if !exist {
				continue
			}
			BelongToID = parentPro.BelongToID
			name = parentPro.Name + "-" + name
		}
		nameToProMap[name] = p
	}
	// 获取文件

	_, f, err := ctx.Request.FormFile("file")
	if err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, fmt.Errorf("文件获取失败, "+err.Error()))
	}
	if !tools.CheckExcleName(f.Filename) {
		return errors.NewErrInfo(http.StatusInternalServerError, fmt.Errorf("不能识别文件，请上传.xlsx格式的文件"))
	}

	f2, err := f.Open()
	if err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, fmt.Errorf("文件打开异常, "+err.Error()))
	}
	b, _ := io.ReadAll(f2)

	f3, err := xlsx.OpenBinary(b)
	if err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, fmt.Errorf("文件读取异常, "+err.Error()))
	}
	dataArr, err := f3.ToSlice()
	if err != nil {
		return errors.NewErrInfo(http.StatusInternalServerError, fmt.Errorf("文件内容格式异常, "+err.Error()))
	}
	for _, sheet := range dataArr {
		for _, row := range sheet {
			first := strings.TrimSpace(row[0])
			second := strings.TrimSpace(row[1])
			third := strings.TrimSpace(row[2])

			var belongToID uint
			// 第一层直接插入
			if first == "" {
				continue
			}
			if f, exist := nameToProMap[first]; exist {
				belongToID = f.ID
			} else {
				insertPro := tables.Profession{
					Tier:       "first",
					Name:       first,
					BelongToID: nil,
				}
				if err := variable.DB.MySQL.Create(&insertPro).Error; err != nil {
					return errors.NewErrInfo(http.StatusInternalServerError, err)
				}
				belongToID = insertPro.ID
				nameToProMap[first] = insertPro
				idToProMap[insertPro.ID] = insertPro
			}
			// 第二层插入
			if second == "" {
				continue
			}
			if f, exist := nameToProMap[first+"-"+second]; exist {
				belongToID = f.ID
			} else {
				insertPro := tables.Profession{
					Tier:       "second",
					Name:       second,
					BelongToID: &belongToID,
				}
				if err := variable.DB.MySQL.Create(&insertPro).Error; err != nil {
					return errors.NewErrInfo(http.StatusInternalServerError, err)
				}
				belongToID = insertPro.ID
				nameToProMap[first+"-"+second] = insertPro
				idToProMap[insertPro.ID] = insertPro
			}
			// 第三层插入
			if third == "" {
				continue
			}
			thirdKey := first + "-" + second + "-" + third
			if _, exist := nameToProMap[thirdKey]; exist {
				continue
			}
			insertPro := tables.Profession{
				Tier:       "third",
				Name:       third,
				BelongToID: &belongToID,
			}
			if err := variable.DB.MySQL.Create(&insertPro).Error; err != nil {
				return errors.NewErrInfo(http.StatusInternalServerError, err)
			}
			belongToID = insertPro.ID
			nameToProMap[thirdKey] = insertPro
			idToProMap[insertPro.ID] = insertPro
		}
	}

	return nil
}
